class Snake {
  head: HTMLElement
  bodies: HTMLCollection
  // 蛇身的容器
  element: HTMLElement
  constructor() {
    // 获取头节点
    this.head = document.querySelector('#snake > li') as HTMLElement
    // 获取身体节点
    this.bodies = document.getElementById('snake')!.getElementsByTagName('li')
    // 获取蛇身的容器
    this.element = document.getElementById('snake') as HTMLElement
  }

  // [x,y] 获取蛇头的坐标
  // 通过get set的方式可以隐藏xy的细节，并且在set时可以对数据进行校验
  get x(): number {
    return this.head.offsetLeft
  }

  set x(value: number) {
    // 值相同时可以不修改style，可以防止一次reflow回流，优化效率
    if (this.x == value) {
      return
    }
    this.moveBody()
    this.head.style.left = value + 'px'
  }

  get y(): number {
    return this.head.offsetTop
  }

  set y(value: number) {
    // 值相同时可以不修改style，可以防止一次reflow回流，优化效率
    if (this.y == value) {
      return
    }
    this.moveBody()
    this.head.style.top = value + 'px'
  }

  // 增加身体节点
  addBody(): void {
    this.element.insertAdjacentHTML("beforeend", "<li></li>")
  }

  // 蛇身移动跟随
  moveBody(): void {
    // 从后往前遍历，后一个身体节点设为上一个身体节点的位置
    for (let i = this.bodies.length - 1; i > 0; i--) {
      const previousBody = this.bodies[i - 1] as HTMLElement
      const body = this.bodies[i] as HTMLElement
      body.style.top = previousBody.offsetTop + 'px'
      body.style.left = previousBody.offsetLeft + 'px'
    }
  }

  checkEatBody(): boolean {
    for (let i = 1; i < this.bodies.length; i++) {
      const body = this.bodies[i] as HTMLElement
      // console.log(this.x, body.offsetLeft, this.y, body.offsetTop)
      if (this.x == body.offsetLeft && this.y == body.offsetTop) {
        // 吃到身体
        return true
      }
    }

    return false
  }
}

export default Snake 